package ru.ipccenter.browser;

import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Stack;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class SMBBrowser {
    {
        String conFile = "log4j.properties";
        PropertyConfigurator.configure(conFile);
    }
    public static final Logger LOGGER = Logger.getLogger(SMBBrowser.class);
    private SmbFile server = null;

    public SMBBrowser(String path) {
        if (path == null) {
            LOGGER.error("Invalid name of server(NULL)");
            throw new RuntimeException("Invalid name of server(NULL)");
        }
        try {
            jcifs.Config.registerSmbURLHandler();
            server = new SmbFile("smb://" + path + "/");
            if (server.exists() & server.canRead()) {
                LOGGER.info("Connection established(" + server.getServer() + ")");
            }
        } catch (MalformedURLException e) {
            this.close();
            LOGGER.error("Bad url");
            throw new RuntimeException("Bad url");
        } catch (SmbException e) {
            this.close();
            LOGGER.error("Bad url or permission denied");
            throw new RuntimeException("Bad url or permission denied");
        }
    }

    public boolean isDir() {
        try {
            return server.isDirectory();
        } catch (SmbException e) {
            LOGGER.warn("isDir fail");
            return false;
        }
    }

    public boolean isFile() {
        try {
            return server.isFile();
        } catch (SmbException e) {
            LOGGER.warn("isFile fail");
            return false;
        }
    }

    public ArrayList<String> ls() throws NullPointerException, SmbException {
        if (!this.isDir()) {
            return null;
        }
        SmbFile[] array = null;
        try {
            array = server.listFiles();
        } catch (SmbException e) {
            LOGGER.error("listFiles fail");
            throw e;
        }
        ArrayList<String> retValue = new ArrayList<String>(array.length);
        for (SmbFile file : array) {
            retValue.add(file.getName());
        }
        return retValue;
    }
    
    public ArrayList<String> search(String regexp, String path) throws MalformedURLException, SmbException {
        ArrayList<String> retValue = new ArrayList<String>();
        Stack stack = new Stack();
        ArrayList<String> black = null;
        ArrayList<String> list = null;
        String vertex = null;
        stack.push("smb://" + path + "/");
        stack.push(new ArrayList<String>());
        while (true) {
            black = (ArrayList<String>)stack.pop();
            vertex = (String)stack.pop();
            String s = null;
            try {
                server = new SmbFile(vertex);
                s = server.getName();
            } catch(Exception ex){
                black = (ArrayList<String>)stack.pop();
                black.add(s);
                stack.push(black);
                continue;
            }
            if (this.isFile() && !black.contains(s)) {
                if (s.matches(regexp)) {
                    retValue.add(vertex);
                }
                if (stack.isEmpty()){
                    break;
                }
                black = (ArrayList<String>)stack.pop();
                black.add(s);
                stack.push(black);
                continue;
            }
            try {
                list = this.ls();
            } catch(Exception ex) {
                if (stack.isEmpty()){
                    break;
                }
                black = (ArrayList<String>)stack.pop();
                black.add(s);
                stack.push(black);
                continue;
            }
            list.removeAll(black);
            if (list.isEmpty()) {
                if (s.matches(regexp)) {
                    retValue.add(vertex);
                }
                if (stack.isEmpty()){
                    break;
                }
                black = (ArrayList<String>)stack.pop();
                black.add(s);
                stack.push(black);
            } else {
                stack.push(vertex);
                stack.push(black);
                stack.push(vertex + list.get(0));
                stack.push(new ArrayList<String>());
            }
        }
        return retValue;
    }
    
    private boolean cd(String newPath) {
        try {
            if (newPath.matches("\".*\"")) {
                newPath = newPath.substring(1, newPath.length() - 1);
            }
            SmbFile tmp = null;
            if (newPath.matches("/.*")) {
                tmp = new SmbFile("smb://" + server.getServer() + newPath + "/");
            } else {
                tmp = new SmbFile(server.getPath() + newPath + "/");
            }
            if (tmp.exists() & tmp.canRead()) {
                if (!tmp.isDirectory()) {
                    return false;
                } else {
                    server = tmp;
                }
            } else {
                return false;
            }
        } catch (MalformedURLException e) {
            LOGGER.warn("Bad url");
            return false;
        } catch (SmbException e) {
            LOGGER.warn("Wrong directory");
            return false;
        } catch (NullPointerException e) {
            LOGGER.warn("Wrong directory(NULL)");
            return false;
        }
        return true;
    }

    public void close() {
        server = null;
        LOGGER.info("Connection closed");
    }
}
